// Package ClientNetIO 客户端连接的缓存模块
package ClientNetIO

import (
	LogUtils "IMServices/LogService"
	"IMServices/LoginService/ClientLoginOrder"
	"IMServices/NetIO/Packet"
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"
)

// TcpTempClient 第一次连接缓存在这里
type TcpTempClient struct {
	//ip
	Ip string
	//端口
	Port int
	//连接时间
	LoginTime time.Time
	//客户端socket
	conn net.Conn
}

// ClientInstance 缓存连接
var ClientInstance map[string]TcpTempClient

func InitNewClientManager() {
	ClientInstance = make(map[string]TcpTempClient)
}

func (client *TcpTempClient) UpdateConn(conn net.Conn) {

	addr := conn.RemoteAddr().String()
	split := strings.Split(addr, ":")
	client.Ip = split[0]
	port, err := strconv.Atoi(split[1])
	if err != nil {
		fmt.Println("strconv.Atoi err", err)
		return
	}
	client.Port = port
	client.LoginTime = time.Now()
	client.conn = conn
}

func AddTempConn(tcpClient TcpTempClient) {
	remoteAddr := tcpClient.conn.RemoteAddr().(*net.TCPAddr)
	ip := remoteAddr.IP.String()
	port := remoteAddr.Port
	ClientInstance[ip+":"+strconv.Itoa(port)] = tcpClient
}

func DelTempConn(ip string, port int) {
	delete(ClientInstance, ip+":"+strconv.Itoa(port))
}

func GetTempConn(ip string, port int) (TcpTempClient, error) {
	if _, ok := ClientInstance[ip+":"+strconv.Itoa(port)]; ok {
		client := ClientInstance[ip+":"+strconv.Itoa(port)]
		return client, nil
	} else {
		LogUtils.LogError(ip + ":" + strconv.Itoa(port) + "连接不存在")
		return TcpTempClient{}, errors.New("连接不存在")
	}
}

func (client *TcpTempClient) StartRead(conn net.Conn) {
	// 循环读取客户端发送数据
	buf := make([]byte, 1024*8*10)
	header := Packet.Header{}
	message := Packet.MessageRequest{}
	var length int
	var ok bool
	var err error
	for {
		length, err = conn.Read(buf)
		if err != nil {
			LogUtils.LogError("conn Read err", err)
			return
		}
		for length > 0 {
			if length < 20 {
				buf = buf[length:]
				length = 0
				LogUtils.LogError("客户端已关闭，断开连接")
				break
			}

			err = binary.Read(bytes.NewReader(buf), binary.BigEndian, &header)
			if err != nil {
				fmt.Println("binary.Read failed:", err)
				return
			}
			if int(header.PacketLength) > length {
				return
			}
			message.MsgHeader = header
			message.MsgBody = buf[header.HeaderLength:header.PacketLength]
			//LogUtils.LogInfo("header packet len = ", header.HeaderLength, "body = ", message.MsgBody)
			var handle func(pack Packet.MessageRequest, conn net.Conn)
			if handle, ok = ClientLoginOrder.MethodMap[header.Method]; !ok {
				LogUtils.LogError("没有这个方法 method = ", header.Method)
				break
			}
			go handle(message, conn)
			buf = buf[header.PacketLength:]
			length = length - int(header.PacketLength)
		}
	}
}
